package com.dotndot.momserver.xml;

import java.io.*;
import java.util.*;

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

import org.w3c.dom.*;

public class XML
{

    public static final int HEADER_TYPE = 0;
    public static final int DATA_TYPE = 1;

    private static final String RESULT = "RESULT";
    private static final String HEADER = "HEADER";
    private static final String DATA = "DATA";
    public static final String CODE = "CODE";
    public static final String MESSAGE = "MESSAGE";

    public static final String USER_KEY = "USER_KEY";
    public static final String ITEM = "ITEM";
    public static final String KEY = "KEY";
    public static final String IMAGE = "IMAGE";
    public static final String DESCRIPTION = "DESCRIPTION";

    public static final String EXIST = "EXIST";
    public static final String NOTHING = "NOTHING";

    public static final String START = "START";
    public static final String END = "END";

    private static List<DataXml> mHeaderList = null;
    private static List<DataXml> mDataList = null;
    private static Stack<Element> mElementStack = null;

    public static void initList()
    {
        if( mHeaderList == null )
        {
            mHeaderList = new ArrayList<DataXml>();
        }
        if( mDataList == null )
        {
            mDataList = new ArrayList<DataXml>();
        }
        if( mElementStack == null )
        {
            mElementStack = new Stack<Element>();
        }
        mHeaderList.clear();
        mDataList.clear();
        mElementStack.clear();
    }

    public static void addHeaderList( DataXml data )
    {
        if( mHeaderList != null )
        {
            mHeaderList.add(data);
        }
    }

    public static void addDataList( DataXml data )
    {
        if( mDataList != null )
        {
            mDataList.add(data);
        }
    }

    public static String makeXml()
    {

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        Element element;

        try
        {
            builder = factory.newDocumentBuilder();
            Document doc = builder.newDocument();

            Element root = doc.createElement(RESULT);
            doc.appendChild(root);

            if( mHeaderList.size() != 0 )
            {
                Element root_header = doc.createElement(HEADER);
                root.appendChild(root_header);

                for( DataXml data : mHeaderList )
                {
                    element = doc.createElement(data.mElement);
                    element.appendChild(doc.createTextNode(data.mData));
                    root_header.appendChild(element);
                }
            }

            if( mDataList.size() != 0 )
            {
                Element root_data = doc.createElement(DATA);
                root.appendChild(root_data);

                for( DataXml data : mDataList )
                {
                    if( data.mData.equals(START) )
                    {
                        element = doc.createElement(data.mElement);
                        root_data.appendChild(element);
                        mElementStack.push(root_data);
                        root_data = element;
                    }
                    else if( data.mData.equals(END) )
                    {
                        // element = doc.createElement(data.mElement);
                        // root_data.appendChild(element);
                        root_data = mElementStack.pop();
                    }
                    else
                    {
                        element = doc.createElement(data.mElement);
                        element.appendChild(doc.createTextNode(data.mData));
                        root_data.appendChild(element);
                    }
                }
            }

            return getDocumentToString(doc);

        }
        catch( ParserConfigurationException e )
        {
            e.printStackTrace();
            return null;
        }
        catch( TransformerException e )
        {
            e.printStackTrace();
            return null;
        }
    }

    public static void makeElement( Document doc, Element root, DataXml data )
    {
        Element child = doc.createElement(data.mElement);
        root.appendChild(child);
        if( data.mData != null )
        {
            child.appendChild(doc.createTextNode(data.mData));
        }
        else
        {
            makeElement(doc, child, data);
        }
    }

    public static String loginXML( String type, String code, String message, String apiKey )
    {

        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder;
        try
        {
            builder = factory.newDocumentBuilder();
            Document doc = builder.newDocument();

            Element root = doc.createElement(type);
            doc.appendChild(root);

            Element codeElement = doc.createElement("CODE");
            root.appendChild(codeElement);
            codeElement.appendChild(doc.createTextNode(code));

            Element msgElement = doc.createElement("MESSAGE");
            root.appendChild(msgElement);
            msgElement.appendChild(doc.createTextNode(message));

            if( apiKey != null )
            {
                Element keyElement = doc.createElement("API_KEY");
                root.appendChild(keyElement);
                keyElement.appendChild(doc.createTextNode(apiKey));
            }

            return getDocumentToString(doc);

        }
        catch( ParserConfigurationException e )
        {
            e.printStackTrace();
            return null;
        }
        catch( TransformerException e )
        {
            e.printStackTrace();
            return null;
        }
    }

    private static String getDocumentToString( Document doc ) throws TransformerException
    {

        StringWriter sw = new StringWriter();
        TransformerFactory transFactory = TransformerFactory.newInstance();
        Transformer trans = transFactory.newTransformer();

        trans.setOutputProperty(OutputKeys.METHOD, "xml");
        trans.setOutputProperty(OutputKeys.INDENT, "yes");
        trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
        trans.setOutputProperty(OutputKeys.STANDALONE, "yes");

        trans.transform(new DOMSource(doc), new StreamResult(sw));
        return sw.getBuffer().toString();
    }

    public static String commonXML( String[] msg )
    {

        try
        {
            DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
            DocumentBuilder builder = factory.newDocumentBuilder();
            DOMImplementation domImplement = builder.getDOMImplementation();
            Document doc = domImplement.createDocument(null, null, null);

            Element root = doc.createElement(msg[0]);
            doc.appendChild(root);

            Element codeElement = doc.createElement("CODE");
            root.appendChild(codeElement);
            codeElement.appendChild(doc.createTextNode(msg[1]));

            Element msgElement = doc.createElement("MESSAGE");
            root.appendChild(msgElement);
            msgElement.appendChild(doc.createTextNode(msg[2]));

            StringWriter sw = new StringWriter();
            TransformerFactory transFactory = TransformerFactory.newInstance();
            Transformer trans = transFactory.newTransformer();

            trans.setOutputProperty(OutputKeys.METHOD, "xml");
            trans.setOutputProperty(OutputKeys.INDENT, "yes");
            trans.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
            trans.setOutputProperty(OutputKeys.STANDALONE, "yes");
            trans.transform(new DOMSource(doc), new StreamResult(sw));

            return sw.getBuffer().toString();

        }
        catch( ParserConfigurationException e )
        {
            e.printStackTrace();
            return null;
        }
        catch( TransformerConfigurationException e )
        {
            e.printStackTrace();
            return null;
        }
        catch( TransformerException e )
        {
            e.printStackTrace();
            return null;
        }
    }
}
